After weeks of tweaking I finally gave up. I just couldn\'t fix my multiple file upload on safari, which really bothered me because my code worked perfectly as it should on
This is oldish question, but ... hack-type workaround is below.
Just remove multiple attribute for Safari, turnig it into MSIE<=9 little brother (non-XHR).
Rest of browsers will not be affected.
When Safari finally fixes problem, all you have to do is remove this hack::code and go back to standard input code.
here is standard input sample:
<input class="fileupload-input" type="file" name="files[]" multiple />
jQuery solution:
Just place it somewhere on a page, where you have files input tag.
you may read more here: How to detect Safari, Chrome, IE, Firefox and Opera browser?
$(document).ready(function () { if (Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor')>0); $('.fileupload-input').removeAttr("multiple"); });
PHP solution
you will need some code to id browser I used a class I got one in github (MIT) get it here: https://github.com/gavroche/php-browser
$files = '<input class="fileupload-input" type="file" name="files[]" multiple />'; if (Browser::getBrowser() === Browser::SAFARI) { $files = '<input class="fileupload-input" type="file" name="files[]" />'; } echo $files
That is all.
I ran into the image.jpg problem with asp.net. It may benefit someone. I was appending a non-unique hash to each image file to tie it to the record in the db. Works fine on every platform (our users are using, anyway), except when using Safari. I just appended a hash and a unique three digit string I pulled from the seconds part of DateTime to string:
if (!string.IsNullOrEmpty(ViewState["HashId"].ToString()))
{
string filepath = Server.MapPath("~/docs/");
HttpFileCollection uploadedFiles = Request.Files;
Span1.Text = string.Empty;
for (int i = 0; i < uploadedFiles.Count; i++)
{
HttpPostedFile userPostedFile = uploadedFiles[i];
try
{
if (userPostedFile.ContentLength > 0)
{
string timestamp = DateTime.UtcNow.ToString("fff",
CultureInfo.InvariantCulture);
//Span1.Text += "<u>File #" + (i + 1) + "</u><br>";
//Span1.Text += "File Content Type: " + userPostedFile.ContentType + "<br>";
//Span1.Text += "File Size: " + userPostedFile.ContentLength + "kb<br>";
//Span1.Text += "File Name: " + userPostedFile.FileName + "<br>";
userPostedFile.SaveAs(filepath + "\\" + ViewState["HashId"] + "_" + Path.GetFileName(timestamp + userPostedFile.FileName));
// Span1.Text += "Location where saved: " + filepath + "\\" + Path.GetFileName(userPostedFile.FileName) + "<p>";
InsertFilename("~/docs/" + ViewState["HashId"] + "_" + Path.GetFileName(timestamp + userPostedFile.FileName), ViewState["HashId"] + "_" + Path.GetFileName(timestamp + userPostedFile.FileName));
}
}
catch (Exception Ex)
{
Span1.Text += "Error: <br>" + Ex.Message;
}
}
BindImages();
SetAttchBitTrue();
Button4.Visible = true;
AttchStatus.Text = "This Record Has Attachments";
Button2.Visible = true;
Button3.Visible = true;
Panel1.Visible = false;
}
May be a better way, but we just have a small number of people uploading one - two, maybe three images per record in the database. Should work.
It seems that there is another issue that can be messing around. iOS Safari multiple file uploads always use the name "image.jpg" for all uploaded files. It may seem only one file uploaded in the server side but this is not what happened: it has been uploaded all files with the same name!
So, the workaround comes into the server side: just change the destination filename with a new generated name.
I am working with Flask and Python, so I use the standard formula.
@app.route("/upload",methods=['POST'])
def upload():
files = request.files.getlist('files[]')
for file in files:
if file and allowed_file(file.filename):
filename = generate_filename(file.filename)
file.save( os.path.join(app.config['UPLOAD_FOLDER'], new_album_id, filename))
return render_template('upload_ok.html')
Where generate_filaname
has to be a function that creates a new filename with the same extension as the original one. For example:
def generate_filename(sample_filename):
# pick up extension from sample filename
ext = sample_filename.split(".")[-1]
name = ''.join( random.SystemRandom().choice(string.letters+string.digits) for i in range(16) )
return name + "." + ext
The same can be done in PHP, of course.