QA@IT
«回答へ戻る

回答を投稿

質問にあがっている環境であれば HTML5環境になると思いますので、以下の様に修正すればいいと思います。

aspx部の修正

最初に本題と関係ないですが、

  • styleタグはheadタグの中に書いた方がいいでしょう。

  • name属性はあくまで名前なので内容が配列かどうかは関係ありません。なので記号は使わない方がいいでしょう。

そして、本題ですが uploadを行うので、formにenctype属性をつける必要があります。

こちらの別の質問での回答のように、Page_Loadなどで設定する方法もありますし、formタグに直接記述する方法もあります。

これらを直すと以下の様なaspxになります(styleとinputタグ以降は省略しています)。

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="test.aspx.vb" Inherits="Test.test" %>
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <style type="text/css">
       ~省略~
    </style>
</head>
<body>
    <form id="form1" runat="server" enctype="multipart/form-data">
        <input type="file" accept="image/jpeg, image/gif, image/png" id="file" name="files" multiple>

~以下略~

VBコード部分の修正

保存ボタン(Button1)を押したイベントでどのように取得するかですが、

単純な取得方法としては、Request.FilesのAllKeysプロパティを利用する方法があります。

Requestされたすべてのファイルを、リクエストされたファイル名で保存するには以下の様にすればいいでしょう。

Request.Filesに引き渡す文字列はキーとなる文字列またはインデックスとなる数値であり、コントロールの名前ではない事に注意してください。

Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Dim SendPath As String = "\\svr\hoge\"  ' 最後に \ を付け足しました

    For Each key In Request.Files.AllKeys

        Dim file = Request.Files(key)
        file.SaveAs(SendPath & Path.GetFileName(file.FileName))
    Next
End Sub

(Path.GetFileNameはフルパスでファイル名を送信してくるブラウザ(IEなど)があるため、ファイル名だけを抽出しています。)

キー文字列ではなく、インデックスでループさせる場合は以下の様にします。

Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Dim SendPath As String = "\\svr\hoge\"  ' 最後に \ を付け足しました

    For i = 0 To Request.Files.Count - 1

        Dim file = Request.Files(i)
        file.SaveAs(SendPath & Path.GetFileName(file.FileName))
    Next
End Sub

ところで、現在はinput[type=file]が一つなのですべて取り出してしまえば問題ありませんが、
これがページ内に複数あった場合は分けて取得したくなると思います、そういう場合は以下の様にすれば個別に取得することができます。

<input type="file" accept="image/jpeg, image/gif, image/png" id="file" name="filesA" multiple>
<input type="file" accept="image/jpeg, image/gif, image/png" id="file" name="filesB" multiple>
    For Each file In Request.Files.GetMultiple("filesA")
        file.SaveAs(SendPath & "A_" & Path.GetFileName(file.FileName))
    Next

    For Each file In Request.Files.GetMultiple("filesB")
        file.SaveAs(SendPath & "B_" & Path.GetFileName(file.FileName))
    Next

この時に渡す文字列はname属性に指定した文字列です。


参考までに、iPhone 6のChromeとsafariで試してみたところ、カメラロールから取得されたファイルのFileNameは全部同じ名前で送信されているようでした。

そして、AllKeysで取れるキーも同一となってしまうようだったので、取り出すときにはAllKeysではなく、インデックスかGetMultipleを使うようにしないと思うような動作にならないかもしれません。

さらに保存の際にも通番などを振るといいでしょう。String.Formatなどでやった方がいいんですが、単純に文字列結合でやると以下の様な感じでしょうか。

    Dim sendPath = "\\svr\hoge\"  ' 最後に \ を付け足しました
    Dim count = 0

    For Each file In Request.Files.GetMultiple("files")
        count = count + 1
        file.SaveAs(SendPath & count & "_" & Path.GetFileName(file.FileName))
    Next

FileUploadコントロールを使う場合

余談になりますが FileUploadコントロールでも複数ファイルの送信は可能です。

複数のファイルを送信する場合はAllowMultiple="true"を指定します。

    <asp:FileUpload ID="fup" runat="server" AllowMultiple="true" />

コード側(Button1_Click)でファイルを取得するには、FileUploadコントロールのPostedFilesプロパティやHasFilesプロパティを使えばいいでしょう。

    For Each file In fup.PostedFiles
        file.SaveAs(SendPath & Path.GetFileName(file.FileName))
    Next

サーバー/アプリケーション設定で気を付けること

ASP.NETやIISではリクエストサイズ規制があるため、複数の写真を送信しようとするとエラーが発生する可能性があります。

asp_net_request_error.png

ASP.NETではhttpRuntime maxRequestLengthの設定(Web.Config)、

IISでは requestLimits, maxAllowedContentLength の設定にも気を付けてください。


最後に、対象がiOSやAndroidということであればHTML5対応ブラウザですので上記方法で問題ないとおもいますが、PCなどHTML5非対応ブラウザをターゲットに入れる場合はAjaxコントロールなどの利用を検討する必要があります。

質問にあがっている環境であれば HTML5環境になると思いますので、以下の様に修正すればいいと思います。

## aspx部の修正

最初に本題と関係ないですが、

* `style`タグは`head`タグの中に書いた方がいいでしょう。

* `name`属性はあくまで名前なので内容が配列かどうかは関係ありません。なので記号は使わない方がいいでしょう。

そして、本題ですが uploadを行うので、formにenctype属性をつける必要があります。

[**こちらの別の質問での回答**][1]のように、Page_Loadなどで設定する方法もありますし、formタグに直接記述する方法もあります。

  [1]:http://qa.atmarkit.co.jp/q/9154#answer_33587


これらを直すと以下の様なaspxになります(styleとinputタグ以降は省略しています)。

```html
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="test.aspx.vb" Inherits="Test.test" %>
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <style type="text/css">
       ~省略~
    </style>
</head>
<body>
    <form id="form1" runat="server" enctype="multipart/form-data">
        <input type="file" accept="image/jpeg, image/gif, image/png" id="file" name="files" multiple>

~以下略~
```

---

## VBコード部分の修正

保存ボタン(Button1)を押したイベントでどのように取得するかですが、

単純な取得方法としては、Request.FilesのAllKeysプロパティを利用する方法があります。  
Requestされたすべてのファイルを、リクエストされたファイル名で保存するには以下の様にすればいいでしょう。  

Request.Filesに引き渡す文字列はキーとなる文字列またはインデックスとなる数値であり、コントロールの名前ではない事に注意してください。

```vb
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Dim SendPath As String = "\\svr\hoge\"  ' 最後に \ を付け足しました

    For Each key In Request.Files.AllKeys

        Dim file = Request.Files(key)
        file.SaveAs(SendPath & Path.GetFileName(file.FileName))
    Next
End Sub
```

(Path.GetFileNameはフルパスでファイル名を送信してくるブラウザ(IEなど)があるため、ファイル名だけを抽出しています。)

キー文字列ではなく、インデックスでループさせる場合は以下の様にします。

```vb
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Dim SendPath As String = "\\svr\hoge\"  ' 最後に \ を付け足しました

    For i = 0 To Request.Files.Count - 1

        Dim file = Request.Files(i)
        file.SaveAs(SendPath & Path.GetFileName(file.FileName))
    Next
End Sub
```


---

ところで、現在はinput[type=file]が一つなのですべて取り出してしまえば問題ありませんが、
これがページ内に複数あった場合は分けて取得したくなると思います、そういう場合は以下の様にすれば個別に取得することができます。

```html
<input type="file" accept="image/jpeg, image/gif, image/png" id="file" name="filesA" multiple>
<input type="file" accept="image/jpeg, image/gif, image/png" id="file" name="filesB" multiple>
```

```vb
    For Each file In Request.Files.GetMultiple("filesA")
        file.SaveAs(SendPath & "A_" & Path.GetFileName(file.FileName))
    Next

    For Each file In Request.Files.GetMultiple("filesB")
        file.SaveAs(SendPath & "B_" & Path.GetFileName(file.FileName))
    Next
```

この時に渡す文字列は`name属性`に指定した文字列です。

---

参考までに、iPhone 6のChromeとsafariで試してみたところ、カメラロールから取得されたファイルのFileNameは全部同じ名前で送信されているようでした。

そして、AllKeysで取れるキーも同一となってしまうようだったので、取り出すときにはAllKeysではなく、インデックスかGetMultipleを使うようにしないと思うような動作にならないかもしれません。  
さらに保存の際にも通番などを振るといいでしょう。String.Formatなどでやった方がいいんですが、単純に文字列結合でやると以下の様な感じでしょうか。

```vb
    Dim sendPath = "\\svr\hoge\"  ' 最後に \ を付け足しました
    Dim count = 0

    For Each file In Request.Files.GetMultiple("files")
        count = count + 1
        file.SaveAs(SendPath & count & "_" & Path.GetFileName(file.FileName))
    Next
```

---

## FileUploadコントロールを使う場合

余談になりますが FileUploadコントロールでも複数ファイルの送信は可能です。  
複数のファイルを送信する場合はAllowMultiple="true"を指定します。

```html
    <asp:FileUpload ID="fup" runat="server" AllowMultiple="true" />
```

コード側(Button1_Click)でファイルを取得するには、FileUploadコントロールのPostedFilesプロパティやHasFilesプロパティを使えばいいでしょう。

```vb
    For Each file In fup.PostedFiles
        file.SaveAs(SendPath & Path.GetFileName(file.FileName))
    Next
```

---

## サーバー/アプリケーション設定で気を付けること

ASP.NETやIISではリクエストサイズ規制があるため、複数の写真を送信しようとするとエラーが発生する可能性があります。

![asp_net_request_error.png](https://qa-atmarkit-image.s3.amazonaws.com/uploads/attached_image/image/31/asp_net_request_error.png)


ASP.NETでは`httpRuntime maxRequestLength`の設定(Web.Config)、

IISでは requestLimits, maxAllowedContentLength の設定にも気を付けてください。

---

最後に、対象がiOSやAndroidということであればHTML5対応ブラウザですので上記方法で問題ないとおもいますが、PCなどHTML5非対応ブラウザをターゲットに入れる場合はAjaxコントロールなどの利用を検討する必要があります。