Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
M
mongoose
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Ganil-acq
GANILinux
linux-service
library
mongoose
Commits
c388bc2d
Commit
c388bc2d
authored
12 years ago
by
Sergey Lyubka
Browse files
Options
Downloads
Patches
Plain Diff
added upload example
parent
8072b0a7
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
examples/upload.c
+130
-0
130 additions, 0 deletions
examples/upload.c
with
130 additions
and
0 deletions
examples/upload.c
0 → 100644
+
130
−
0
View file @
c388bc2d
// Copyright (c) 2004-2012 Sergey Lyubka
// This file is a part of mongoose project, http://github.com/valenok/mongoose
#include
<stdio.h>
#include
<string.h>
#include
<fcntl.h>
#include
<stdlib.h>
#include
<inttypes.h>
#include
<unistd.h>
#include
"mongoose.h"
// Make sure that form has enctype="multipart/form-data" attribute
static
const
char
*
html_form
=
"<html><body>Upload example."
"<form method=
\"
POST
\"
action=
\"
/handle_post_request
\"
"
" enctype=
\"
multipart/form-data
\"
>"
"<input type=
\"
file
\"
name=
\"
file
\"
/> <br/>"
"<input type=
\"
submit
\"
value=
\"
Upload
\"
/>"
"</form></body></html>"
;
static
const
char
*
HTTP_500
=
"HTTP/1.0 500 Server Error
\r\n\r\n
"
;
static
void
handle_file_upload
(
struct
mg_connection
*
conn
)
{
const
char
*
cl_header
;
char
post_data
[
16
*
1024
],
path
[
999
],
file_name
[
1024
],
mime_type
[
100
],
buf
[
BUFSIZ
],
*
eop
,
*
s
,
*
p
;
FILE
*
fp
;
long
long
int
cl
,
written
;
int
fd
,
n
,
post_data_len
;
// Figure out total content length. Return if it is not present or invalid.
cl_header
=
mg_get_header
(
conn
,
"Content-Length"
);
if
(
cl_header
==
NULL
||
(
cl
=
strtoll
(
cl_header
,
NULL
,
10
))
<=
0
)
{
mg_printf
(
conn
,
"%s%s"
,
HTTP_500
,
"Invalid Conent-Length"
);
return
;
}
// Read the initial chunk into memory. This should be multipart POST data.
// Parse headers, where we should find file name and content-type.
post_data_len
=
mg_read
(
conn
,
post_data
,
sizeof
(
post_data
));
file_name
[
0
]
=
mime_type
[
0
]
=
'\0'
;
for
(
s
=
p
=
post_data
;
p
<
&
post_data
[
post_data_len
];
p
++
)
{
if
(
p
[
0
]
==
'\r'
&&
p
[
1
]
==
'\n'
)
{
if
(
s
==
p
)
{
p
+=
2
;
break
;
// End of headers
}
p
[
0
]
=
p
[
1
]
=
'\0'
;
sscanf
(
s
,
"Content-Type: %99s"
,
mime_type
);
// TODO(lsm): don't expect filename to be the 3rd field,
// parse the header properly instead.
sscanf
(
s
,
"Content-Disposition: %*s %*s filename=
\"
%1023[^
\"
]"
,
file_name
);
s
=
p
+
2
;
}
}
// Finished parsing headers. Now "p" points to the first byte of data.
// Calculate file size
cl
-=
p
-
post_data
;
// Subtract headers size
cl
-=
strlen
(
post_data
);
// Subtract the boundary marker at the end
cl
-=
6
;
// Subtract "\r\n" before and after boundary
// Construct destination file name. Write to /tmp, do not allow
// paths that contain slashes.
if
((
s
=
strrchr
(
file_name
,
'/'
))
==
NULL
)
{
s
=
file_name
;
}
snprintf
(
path
,
sizeof
(
path
),
"/tmp/%s"
,
s
);
if
(
file_name
[
0
]
==
'\0'
)
{
mg_printf
(
conn
,
"%s%s"
,
HTTP_500
,
"Can't get file name"
);
}
else
if
(
cl
<=
0
)
{
mg_printf
(
conn
,
"%s%s"
,
HTTP_500
,
"Empty file"
);
}
else
if
((
fd
=
open
(
path
,
O_CREAT
|
O_TRUNC
|
O_WRONLY
|
O_EXLOCK
|
O_CLOEXEC
))
<
0
)
{
// We're opening the file with exclusive lock held. This guarantee us that
// there is no other thread can save into the same file simultaneously.
mg_printf
(
conn
,
"%s%s"
,
HTTP_500
,
"Cannot open file"
);
}
else
if
((
fp
=
fdopen
(
fd
,
"w"
))
==
NULL
)
{
mg_printf
(
conn
,
"%s%s"
,
HTTP_500
,
"Cannot reopen file stream"
);
close
(
fd
);
}
else
{
// Success. Write data into the file.
eop
=
post_data
+
post_data_len
;
n
=
p
+
cl
>
eop
?
(
int
)
(
eop
-
p
)
:
(
int
)
cl
;
(
void
)
fwrite
(
p
,
1
,
n
,
fp
);
written
=
n
;
while
(
written
<
cl
&&
(
n
=
mg_read
(
conn
,
buf
,
cl
-
written
>
(
long
long
)
sizeof
(
buf
)
?
sizeof
(
buf
)
:
cl
-
written
))
>
0
)
{
(
void
)
fwrite
(
buf
,
1
,
n
,
fp
);
written
+=
n
;
}
(
void
)
fclose
(
fp
);
mg_printf
(
conn
,
"HTTP/1.0 200 OK
\r\n\r\n
"
"Saved to [%s], written %llu bytes"
,
path
,
cl
);
}
}
static
void
*
callback
(
enum
mg_event
event
,
struct
mg_connection
*
conn
)
{
const
struct
mg_request_info
*
ri
=
mg_get_request_info
(
conn
);
if
(
event
==
MG_NEW_REQUEST
)
{
if
(
!
strcmp
(
ri
->
uri
,
"/handle_post_request"
))
{
handle_file_upload
(
conn
);
}
else
{
// Show HTML form.
mg_printf
(
conn
,
"HTTP/1.0 200 OK
\r\n
"
"Content-Length: %d
\r\n
"
"Content-Type: text/html
\r\n\r\n
%s"
,
(
int
)
strlen
(
html_form
),
html_form
);
}
// Mark as processed
return
""
;
}
else
{
return
NULL
;
}
}
int
main
(
void
)
{
struct
mg_context
*
ctx
;
const
char
*
options
[]
=
{
"listening_ports"
,
"8080"
,
NULL
};
ctx
=
mg_start
(
&
callback
,
NULL
,
options
);
getchar
();
// Wait until user hits "enter"
mg_stop
(
ctx
);
return
0
;
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment